package com.fqgj.sentry.biz.pc;


import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.JSONUtils;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.sentry.biz.pc.vo.rule.CommonRuleVo;
import com.fqgj.sentry.biz.pc.vo.rule.RuleVo;
import com.fqgj.sentry.common.exception.BizException;
import com.fqgj.sentry.common.exception.enums.ErrorCodeEnums;
import com.fqgj.sentry.controller.pc.request.rule.RuleAddVo;
import com.fqgj.sentry.controller.pc.request.rule.RuleSortItemVo;
import com.fqgj.sentry.controller.pc.request.rule.RuleSortVo;
import com.fqgj.sentry.controller.pc.request.rule.RuleUpdateVo;
import com.fqgj.sentry.controller.pc.request.rule.addAndUpdate.*;
import com.fqgj.sentry.policy.client.ColumnService;
import com.fqgj.sentry.policy.client.PolicyExecutorService;
import com.fqgj.sentry.policy.client.RuleService;
import com.fqgj.sentry.policy.domain.rule.RuleAddAndUpdateInfo;
import com.fqgj.sentry.policy.domain.rule.RuleColumnInfo;
import com.fqgj.sentry.policy.engine.domain.*;
import com.fqgj.sentry.policy.engine.domain.enums.RuleTypeEnum;

import com.fqgj.sentry.policy.entity.PcColumnEntity;
import com.fqgj.sentry.policy.entity.PcExecutorEntity;
import com.fqgj.sentry.policy.entity.PcRuleEntity;
import com.fqgj.sentry.policy.enums.ActiveEnum;
import com.fqgj.sentry.policy.enums.ColumnStatusEnum;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by ykpbean kangping.ying@yuntu-inc.com
 *
 * @description
 * @create 2017-07-29 下午3:35
 */

@Component
public class RuleBusiness {
    @Autowired
    private RuleService ruleService;
    @Autowired
    private PolicyExecutorService policyExecutorService;
    @Autowired
    private ColumnService columnService;

    /**
     * 规则查询
     *
     * @param policyId
     * @return
     */
    public List<RuleVo> findRuleList(Long policyId) {
        List<PcRuleEntity> ruleEntityList = ruleService.findRuleListByPolicyId(policyId, ActiveEnum.all.getType(), com.fqgj.sentry.policy.enums.RuleTypeEnum.custom.getType());
        return transformRuleEntity(ruleEntityList);
    }

    /**
     * 查询策略前置规则
     *
     * @param policyId
     * @return
     */
    public CommonRuleVo findCommonRuleByPolicy(Long policyId) {
        CommonRuleVo commonRuleVo = new CommonRuleVo();
        Rule rule = null;
        PcRuleEntity entity = ruleService.findCommonRuleByPolicy(policyId);
        if (entity != null) {
            String condition = ruleService.findRuleCondition(entity.getId());
            if (StringUtils.isNotEmpty(condition)) {
                try {
                    rule = JSONUtils.json2pojo(condition, Rule.class);
                } catch (Exception e) {
                    throw new BizException(ErrorCodeEnums.json_transform_error);
                }
            }
            commonRuleVo.setRule(rule);
            RuleVo ruleVo = new RuleVo();
            ruleVo.setRuleId(entity.getId())
                    .setCode(entity.getCode())
                    .setIsActive(entity.getIsActive())
                    .setPolicyId(policyId)
                    .setVersion(entity.getVersion())
                    .setName(entity.getName());

            commonRuleVo.setRuleInfo(ruleVo);

        }


        return commonRuleVo;
    }


    /**
     * 规则条件 查询
     *
     * @param ruleId
     * @return
     */
    public Rule ruleCondition(Long ruleId) {
        Rule rule = new Rule();
        String condition = ruleService.findRuleCondition(ruleId);
        if (StringUtils.isNotEmpty(condition)) {
            try {
                rule = JSONUtils.json2pojo(condition, Rule.class);
                rule.setRuleName(ruleService.findById(rule.getRuleId()).getName());
                if (rule.getConditionGroups().size() != 0) {
                    for (ConditionGroup conditionGroup : rule.getConditionGroups()) {
                        if (conditionGroup.getConditions().size() != 0) {
                            for (int i = 0; i < conditionGroup.getConditions().size(); i++) {
                                if (conditionGroup.getConditions().get(i).getSecondVariable().getIsVar()) {
                                    PcColumnEntity entity = columnService.findById(conditionGroup.getConditions().get(i).getSecondVariable().getVariable().getId());
                                    conditionGroup.getConditions().get(i).getSecondVariable().getVariable().setDisplayName(ColumnStatusEnum.getEnumByType(entity.getStatus()).getDesc() + "_" + entity.getDisplayName());
                                }
                            }
                        }
                        if (conditionGroup.getScoreCalculator() != null && conditionGroup.getScoreCalculator().getVariable() != null) {
                            if (conditionGroup.getScoreCalculator().getVariable().getIsVar()) {
                                PcColumnEntity entity = columnService.findById(conditionGroup.getScoreCalculator().getVariable().getVariable().getId());
                                conditionGroup.getScoreCalculator().getVariable().getVariable().setDisplayName(ColumnStatusEnum.getEnumByType(entity.getStatus()).getDesc() + "_" + entity.getDisplayName());
                            }
                        }
                    }
                }
            } catch (Exception e) {
                throw new BizException(ErrorCodeEnums.json_transform_error);
            }
        }
        return rule;
    }

    /**
     * 规则 删除
     *
     * @param ruleIds
     */
    public void ruleDelete(List<Long> ruleIds) {
        ruleService.deleteRule(ruleIds);
    }

    /**
     * 规则状态 更改
     *
     * @param ruleIds
     */
    public void updateRuleActive(List<Long> ruleIds, Integer activeType) {
        ActiveEnum activeEnum = ActiveEnum.getEnumByType(activeType);
        ruleService.updateRuleActive(ruleIds, activeEnum);
    }


    /**
     * 根据规则  code查询规则
     */
    public List<RuleVo> findByCondition(String code) {
        List<PcRuleEntity> ruleEntityList = ruleService.findRuleListByCode(code);
        return transformRuleEntity(ruleEntityList);
    }

    public List<RuleVo> transformRuleEntity(List<PcRuleEntity> ruleEntityList) {
        List<RuleVo> ruleVoList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(ruleEntityList)) {
            for (PcRuleEntity ruleEntity : ruleEntityList) {
                PcExecutorEntity executorEntity = policyExecutorService.selectByExecutorId(ruleEntity.getExecutorId());
                RuleVo ruleVo = new RuleVo();
                BeanUtils.copyProperties(ruleEntity, ruleVo);
                ruleVo.setRuleId(ruleEntity.getId())
                        .setExecutorType(executorEntity.getType())
                        .setExecutorVersion(executorEntity.getVersion())
                        .setExecutorVersionStatus(executorEntity.getVersionStatus());
                ruleVoList.add(ruleVo);
            }
        }
        return ruleVoList;
    }


    /**
     * 规则 新增
     *
     * @param ruleAddVo
     */
    public void addRule(RuleAddVo ruleAddVo) {
        RuleAddAndUpdateInfo addInfo = new RuleAddAndUpdateInfo();
        BeanUtils.copyProperties(ruleAddVo, addInfo);
        RuleTypeEnum ruleTypeEnum = ruleAddVo.getRule().getRuleType();
        addInfo.setRuleType(ruleTypeEnum.ordinal() + 1);
        try {
            addInfo.setRule(JSONUtils.obj2json(ruleAddVo.getRule()));
        } catch (Exception e) {
            throw new BizException(ErrorCodeEnums.json_transform_error);
        }
        //根据规则  获取字段集合
        addInfo.setColumnInfoList(getColumnList(ruleAddVo.getRule()));
        ruleService.addRule(addInfo);
    }

    /**
     * 根据规则  获取关联字段
     *
     * @return
     */
    private List<RuleColumnInfo> getColumnList(RuleAddUpdateVo rule) {
        List<RuleColumnInfo> ruleColumnInfoList = new ArrayList<>();
        try {
            //权重变量
            if (rule.getWeight() != null) {
                VariableVo variable = rule.getWeight().getVariable();
                if (variable != null) {
                    ruleColumnInfoList.add(new RuleColumnInfo(variable.getId(), columnService.findById(variable.getId()).getColumnCode()));
                }
            }
            List<ConditionGroupVo> conditionGroups = rule.getConditionGroups();
            if (CollectionUtils.isNotEmpty(conditionGroups)) {
                for (ConditionGroupVo conditionGroup : conditionGroups) {
                    //评分卡 变量
                    if (conditionGroup.getScoreCalculator() != null) {
                        VariableOrConstantVo variableOrConstant = conditionGroup.getScoreCalculator().getVariable();
                        if (variableOrConstant != null) {
                            if (variableOrConstant.getIsVar()) {
                                VariableVo variable = variableOrConstant.getVariable();
                                if (variable != null) {
                                    ruleColumnInfoList.add(new RuleColumnInfo(variable.getId(), columnService.findById(variable.getId()).getColumnCode()));
                                } else {
                                    throw new BizException(ErrorCodeEnums.rule_object_error, "评分卡字段不能为空！");
                                }
                            } else {
                                if (variableOrConstant.getConstant() == null) {
                                    throw new BizException(ErrorCodeEnums.rule_object_error, "常量字段不能为空");
                                }
                            }
                        }
                    }
                    //条件变量
                    List<ConditionVo> conditions = conditionGroup.getConditions();
                    if (CollectionUtils.isNotEmpty(conditions)) {
                        for (ConditionVo condition : conditions) {
                            VariableVo firstVariable = condition.getFirstVariable();
                            if (firstVariable != null) {
                                ruleColumnInfoList.add(new RuleColumnInfo(firstVariable.getId(), columnService.findById(firstVariable.getId()).getColumnCode()));
                            } else {
                                throw new BizException(ErrorCodeEnums.rule_object_error, "条件字段不能为空");
                            }
                            VariableOrConstantVo secondVariable = condition.getSecondVariable();
                            if (secondVariable != null) {
                                if (secondVariable.getIsVar()) {
                                    VariableVo variable = secondVariable.getVariable();
                                    if (variable != null) {
                                        ruleColumnInfoList.add(new RuleColumnInfo(variable.getId(), columnService.findById(variable.getId()).getColumnCode()));
                                    } else {
                                        throw new BizException(ErrorCodeEnums.rule_object_error, "条件字段不能为空");
                                    }
                                } else {
                                    if (secondVariable.getConstant() == null) {
                                        throw new BizException(ErrorCodeEnums.rule_object_error, "常量字段不能为空");
                                    }
                                }

                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new BizException(ErrorCodeEnums.rule_object_error);
        }
        return ruleColumnInfoList;
    }


    /**
     * 规则 修改
     *
     * @param ruleUpdateVo
     */
    public void updateRule(Long ruleId, RuleUpdateVo ruleUpdateVo) {
        RuleAddAndUpdateInfo updateInfo = new RuleAddAndUpdateInfo();
        if (StringUtils.isEmpty(ruleUpdateVo.getName())) {
            throw new BizException(ErrorCodeEnums.json_transform_error, "规则名称不能为空~");
        }
        updateInfo.setName(ruleUpdateVo.getName());
        try {
            updateInfo.setRule(JSONUtils.obj2json(ruleUpdateVo.getRule()));
        } catch (Exception e) {
            throw new BizException(ErrorCodeEnums.json_transform_error);
        }
        updateInfo.setColumnInfoList(getColumnList(ruleUpdateVo.getRule()));
        ruleService.updateRule(ruleId, updateInfo);
    }


    /**
     * 规则 排序
     *
     * @param ruleSortVo
     * @return
     */
    public void updateRuleSort(RuleSortVo ruleSortVo) {
        List<RuleSortItemVo> ruleSortList = ruleSortVo.getRuleSortList();
        if (CollectionUtils.isEmpty(ruleSortList) || ruleSortList.size() == 1) {
            throw new BizException(ErrorCodeEnums.sort_error, "策略集合需大于1可排序~~");
        }
        for (RuleSortItemVo ruleItem : ruleSortList) {
            ruleService.updateRuleSort(ruleItem.getRuleId(), ruleItem.getSort());
        }
    }

}
